import React from 'react'
import { connect } from 'react-redux'
import { messages } from "share/common"
import { Form, Icon, Tooltip, Input, Select } from 'antd'
const Option = Select.Option;

import 'styles/feedback/cropper.scss'

let intervalId;
class CanvasEdit extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      canvasUrl: '',
      controlBarStyle: {},
      canvasStyle: {
        width: 0,
        height: 0,
        top: 0,
        left: 0
      },
      isMouseDown: false, //鼠标mouseDown时为true，mouseUp时为false
      mouseX: 0, //鼠标落下时的X
      mouseY: 0, //鼠标落下时的Y
      startMouseX: 0,
      startMouseY: 0,
      printType: '', //绘制类型：文字(word)、画笔(pencil)、圆(circle)、矩形(rect)
      printStyle: {}, //绘制样式 {word: {size: '', color: ''}, ...}
      barVisibleType: '', //显示子bar的type
      saveImageData: [], //每次编辑后的canvas
      inputWord: '',
      inputWordBorderWidth: 0,
      inputWordBorderHeight: 0,
      wordFontSize: 14, //文字字体大小
      showWordCursor: false, //文字光标
      wordCursorVisible: true,
    }
  }

  componentDidMount() {
    this.setCanvasImg();
    intervalId = setInterval(() => {
      this.setState({ wordCursorVisible: !this.state.wordCursorVisible })
    }, 700)
  }

  //设置canvas的背景图
  setCanvasImg = () => {
    let img = new Image();
    img.src = this.props.imgUrl;
    img.onload = () => {
      let controlBarStyle = {
        display: 'block',
        top: document.body.clientHeight * .85 + 10,
        right: document.body.clientWidth * .1
      };
      let canvasStyle = {
        width: document.body.clientWidth * .8,
        height: document.body.clientHeight * .8,
        top: document.body.clientHeight * .05,
        left: document.body.clientWidth * .1
      };
      this.setState({ controlBarStyle, canvasStyle }, () => {
        let c = document.getElementById("myCanvas");
        let ctx = c.getContext('2d');
        ctx.drawImage(img, 0, 0, canvasStyle.width, canvasStyle.height);
        this.setState({ saveImageData: [ctx.getImageData(0, 0, canvasStyle.width, canvasStyle.height)] })
      })
    }
  };

  //取消编辑
  editCancel = () => {
    clearInterval(intervalId);
    this.props.onCancel()
  };

  //完成编辑
  editOk = () => {
    clearInterval(intervalId);
    if (document.getElementById("myCanvas") && document.getElementById("myCanvas").toDataURL('image/jpeg', 1) !== this.state.canvasUrl) {
      this.setState({ canvasUrl: document.getElementById("myCanvas").toDataURL('image/jpeg', 1) }, () => {
        this.props.onOK(this.state.canvasUrl)
      })
    } else {
      this.props.onOK(this.state.canvasUrl)
    }
  };

  //设置编辑canvas的类型
  handleCanvasPrint = (type) => {
    this.setState({
      printType: type,
      barVisibleType: type
    })
  };

  //画笔
  drawPencil = () => {
    const { mouseX, mouseY, canvasStyle, isMouseDown, printType, printStyle } = this.state;
    let x = mouseX - canvasStyle.left;
    let y = mouseY - canvasStyle.top;
    let c = document.getElementById("myCanvas");
    let ctx = c.getContext('2d');
    ctx.lineWidth = printStyle[printType] ? (printStyle[printType].size || 1) : 1;
    ctx.strokeStyle = printStyle[printType] ? (printStyle[printType].color || '#5f5f5f') : '#5f5f5f';
    if (!isMouseDown) {
      ctx.beginPath();
      ctx.lineCap = "round";
      ctx.moveTo(x, y);
    } else {
      ctx.lineTo(x, y);
      ctx.stroke(); // 调用绘制方法
    }
  };

  //矩形
  drawRect = () => {
    const { mouseX, mouseY, canvasStyle, isMouseDown, printType, printStyle, startMouseX, startMouseY, saveImageData } = this.state;
    let startX = startMouseX - canvasStyle.left;
    let startY = startMouseY - canvasStyle.top;
    let width = mouseX - canvasStyle.left - startX;
    let height = mouseY - canvasStyle.top - startY;
    let c = document.getElementById("myCanvas");
    let ctx = c.getContext('2d');
    ctx.lineWidth = printStyle[printType] ? (printStyle[printType].size || 1) : 1;
    ctx.strokeStyle = printStyle[printType] ? (printStyle[printType].color || '#5f5f5f') : '#5f5f5f';
    if (isMouseDown) {
      ctx.putImageData(saveImageData[saveImageData.length - 1], 0, 0);
      ctx.beginPath();
      ctx.strokeRect(startX, startY, width, height);
    }
  };

  /**
   * 均匀压缩法绘制椭圆
   * @param ctx
   * @param x 椭圆中心横坐标
   * @param y 椭圆中心纵坐标
   * @param a 椭圆横半轴长
   * @param b 椭圆纵半轴长
   */
  drawEllipseFunc = (ctx, x, y, a, b) => {
    const { printStyle, printType } = this.state;
    ctx.lineWidth = printStyle[printType] ? (printStyle[printType].size || 1) : 1;
    ctx.strokeStyle = printStyle[printType] ? (printStyle[printType].color || '#5f5f5f') : '#5f5f5f';
    ctx.save();
    //选择a、b中的较大者作为arc方法的半径参数
    let r = (a > b) ? a : b;
    let ratioX = a / r; //横轴缩放比率
    let ratioY = b / r; //纵轴缩放比率
    ctx.scale(ratioX, ratioY); //进行缩放（均匀压缩）
    ctx.beginPath();
    //从椭圆的左端点开始逆时针绘制
    ctx.moveTo((x + a) / ratioX, y / ratioY);
    ctx.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.restore();
    ctx.stroke();
  };

  //圆
  drawCircle = () => {
    const { mouseX, mouseY, canvasStyle, isMouseDown, startMouseX, startMouseY, saveImageData } = this.state;
    let c = document.getElementById("myCanvas");
    let ctx = c.getContext('2d');
    let a = Math.abs(mouseX - startMouseX) / 2;
    let b = Math.abs(mouseY - startMouseY) / 2;
    let x = mouseX > startMouseX ? (startMouseX - canvasStyle.left) + a : (startMouseX - canvasStyle.left) - a;
    let y = mouseY > startMouseY ? (startMouseY - canvasStyle.top) + b : (startMouseY - canvasStyle.top) - b;
    if (isMouseDown) {
      ctx.putImageData(saveImageData[saveImageData.length - 1], 0, 0);
      this.drawEllipseFunc(ctx, x, y, a, b)
    }
  };

  //文字
  drawWord = () => {
    const { startMouseX, startMouseY, saveImageData, inputWord, canvasStyle, printStyle, printType, wordFontSize } = this.state;
    let c = document.getElementById("myCanvas");
    let ctx = c.getContext('2d');
    ctx.putImageData(saveImageData[saveImageData.length - 1], 0, 0);
    ctx.font = `${wordFontSize}px Arial`;
    ctx.fillStyle = printStyle[printType] ? (printStyle[printType].color || '#5f5f5f') : '#5f5f5f';
    ctx.fillText(inputWord, startMouseX - canvasStyle.left, startMouseY - canvasStyle.top);
    this.setState({ showWordCursor: true })
  };

  /**
   * 选择尺寸或颜色
   * @param type 尺寸(size)、颜色(color)
   * @param value
   */
  selectSizeOrColor = (type, value) => {
    let printStyle = this.state.printStyle;
    printStyle[this.state.printType] = printStyle[this.state.printType] || {};
    printStyle[this.state.printType][type] = value;
    this.setState({ printStyle })
  };

  //撤销对canvas的编辑
  rollBackEditCanvas = () => {
    let saveImageData = this.state.saveImageData;
    if (saveImageData.length > 1) { //saveImageData的第一个状态是canvas初始状态，最后一个状态是当前状态
      saveImageData.splice(saveImageData.length - 1, 1);
    }
    this.setState({ saveImageData });
    if (saveImageData.length > 0) {
      let c = document.getElementById("myCanvas");
      let ctx = c.getContext('2d');
      ctx.putImageData(saveImageData[saveImageData.length - 1], 0, 0);
      this.setState({ canvasUrl: c.toDataURL('image/jpeg', 1) })
    }
  };

  // 鼠标在canvas上按下时获取鼠标位置
  handleCanvasMouseDown = (e) => {
    this.setState({
      isMouseDown: true,
      mouseX: e.clientX,
      mouseY: e.clientY,
      startMouseX: e.clientX,
      startMouseY: e.clientY
    })
  };

  // 每次mouseUp都保存一次画布状态
  // 文字模式下有一层input覆盖到了canvas上，所以不会触发canvas的onMouseUp
  handleCanvasMouseUp = (e) => {
    this.setState({ isMouseDown: false });
    if (document.getElementById("myCanvas").toDataURL('image/jpeg', 1) !== this.state.canvasUrl) {
      this.setState({
        mouseX: e.clientX,
        mouseY: e.clientY,
        canvasUrl: document.getElementById("myCanvas").toDataURL('image/jpeg', 1)
      }, () => {
        let c = document.getElementById("myCanvas");
        let ctx = c.getContext('2d');
        let saveImageData = this.state.saveImageData;
        saveImageData.push(ctx.getImageData(0, 0, this.state.canvasStyle.width, this.state.canvasStyle.height));
        this.setState({ saveImageData })
      })
    }
  };

  // 添加画笔、圆、矩形模式下，鼠标移动时获取当前鼠标位置并画图
  handleCanvasMouseMove = (e) => {
    this.setState({
      mouseX: e.clientX,
      mouseY: e.clientY
    }, () => {
      const { printType } = this.state;
      printType === 'pencil' && this.drawPencil();
      printType === 'rect' && this.drawRect();
      printType === 'circle' && this.drawCircle()
    })
  };

  // 添加文字模式下，获取输入文字的光标位置
  // 每次添加文字前先对比canvas状态，若不同则先保存当前状态
  handleInputMouseDown = (e) => {
    document.getElementsByClassName('canvas-input-word')[0].value = '';
    this.setState({
      startMouseX: e.clientX,
      startMouseY: e.clientY,
      inputWord: '',
      showWordCursor: true,
      inputWordBorderWidth: 0
    });
    if (document.getElementById("myCanvas").toDataURL('image/jpeg', 1) !== this.state.canvasUrl) {
      let c = document.getElementById("myCanvas");
      let ctx = c.getContext('2d');
      let saveImageData = this.state.saveImageData;
      saveImageData.push(ctx.getImageData(0, 0, this.state.canvasStyle.width, this.state.canvasStyle.height));
      this.setState({
        saveImageData,
        canvasUrl: document.getElementById("myCanvas").toDataURL('image/jpeg', 1)
      })
    }
  };

  // 添加文字模式下，文字发生变化时获取当前输入的文字及文字宽度然后画到canvas上
  handleWordChange = (e) => {
    if (this.state.showWordCursor) {
      let c = document.getElementById("myCanvas");
      let ctx = c.getContext('2d');
      this.setState({
        inputWord: e.target.value,
        inputWordBorderWidth: ctx.measureText(e.target.value).width
      },() => {
        this.state.printType === 'word' && this.state.showWordCursor && this.drawWord()
      })
    }
  };

  // 点击div.control-bar
  // 主要是为了在文字编辑时切换control-bar可以将当前编辑的文字保存到canvas上
  handleControlBarClick = () => {
    this.setState({
      inputWord: '',
      showWordCursor: false,
    });
    if (document.getElementById("myCanvas") && document.getElementById("myCanvas").toDataURL('image/jpeg', 1) !== this.state.canvasUrl) {
      let c = document.getElementById("myCanvas");
      let ctx = c.getContext('2d');
      let saveImageData = this.state.saveImageData;
      saveImageData.push(ctx.getImageData(0, 0, this.state.canvasStyle.width, this.state.canvasStyle.height));
      this.setState({
        saveImageData,
        canvasUrl: document.getElementById("myCanvas").toDataURL('image/jpeg', 1)
      })
    }
  };

  render() {
    const { controlBarStyle, canvasStyle, printType, printStyle, barVisibleType, saveImageData,
      startMouseX, startMouseY, inputWordBorderWidth, wordFontSize, showWordCursor, inputWord, wordCursorVisible } = this.state;
    let printStyleSize = printStyle[printType] ? (printStyle[printType].size || 1) : 1;
    let printStyleColor = printStyle[printType] ? (printStyle[printType].color || 'black') : 'black';
    let sizeColorBar = (
      <div className="size-color-bar">
        {printType === 'word' ? (
          <Select size="small"
                  style={{width: 70}}
                  value={wordFontSize}
                  getPopupContainer={() => document.getElementsByClassName('word-select-container')[0]}
                  onChange={value => this.setState({wordFontSize: value})}>
            <Option value={14}>{messages('feedback.key1'/*小*/)}</Option>
            <Option value={20}>{messages('feedback.key2'/*中*/)}</Option>
            <Option value={30}>{messages('feedback.key3'/*大*/)}</Option>
          </Select>
        ) : (
          <div style={{display: 'inline-block'}}>
            <span className={`size-1 ${printStyleSize === 1 ? 'selected' : ''}`}
                  onClick={() => {this.selectSizeOrColor('size', 1)}}/>
            <span className={`size-5 ${printStyleSize === 5 ? 'selected' : ''}`}
                  onClick={() => {this.selectSizeOrColor('size', 5)}}/>
            <span className={`size-10 ${printStyleSize === 10 ? 'selected' : ''}`}
                  onClick={() => {this.selectSizeOrColor('size', 10)}}/>
          </div>
        )}
        <span className="ant-divider" />
        <span className={`color-black ${printStyleColor === 'black' ? 'selected' : ''}`}
              onClick={() => {this.selectSizeOrColor('color', 'black')}}/>
        <span className={`color-red ${printStyleColor === 'red' ? 'selected' : ''}`}
              onClick={() => {this.selectSizeOrColor('color', 'red')}}/>
        <span className={`color-green ${printStyleColor === 'green' ? 'selected' : ''}`}
              onClick={() => {this.selectSizeOrColor('color', 'green')}}/>
      </div>
    );
    let isTooltipShowBottom = controlBarStyle.top + 43 + 44 <= document.body.clientHeight; //43: div.control-bar的高，44：tooltip的高
    let canvasWordBorderStyle = {
      top: startMouseY - canvasStyle.top,
      left: startMouseX - canvasStyle.left,
      marginTop: wordFontSize === 14 ? -20 : wordFontSize === 20 ? -25 : -34,
      marginLeft: -12,
      width: inputWordBorderWidth + 28,
      height: wordFontSize === 14 ? 30 : wordFontSize === 20 ? 37 : 48
    };
    let canvasWordCursorStyle = {
      width: inputWordBorderWidth,
      height: wordFontSize === 14 ? 20 : wordFontSize === 20 ? 27 : 38,
      borderColor: printStyle.word ? (printStyle.word.color || '#5f5f5f') : '#5f5f5f'
    };
    return (
      <div className='feedback-cropper'>
        <div className="only-canvas-edit-container">
          <div className="canvas-container">
            <div style={{overflow: 'hidden'}}>
              <canvas id="myCanvas" width={canvasStyle.width} height={canvasStyle.height} style={canvasStyle}
                      onMouseDown={this.handleCanvasMouseDown}
                      onMouseUp={this.handleCanvasMouseUp}
                      onMouseMove={this.handleCanvasMouseMove}
              >
                Fallback content, in case the browser does not support Canvas.
              </canvas>
              {printType === 'word' && (
                <Input ref="blur" style={canvasStyle}
                       className="canvas-input-word"
                       value={inputWord}
                       onMouseDown={this.handleInputMouseDown}
                       onChange={this.handleWordChange}/>
              )}
              {printType === 'word' && showWordCursor && (
                <div style={canvasStyle} className="canvas-word-border-container">
                  <div style={canvasWordBorderStyle} className="canvas-word-border">
                    {wordCursorVisible && <span style={canvasWordCursorStyle} className="canvas-word-cursor"/>}
                  </div>
                </div>
              )}
            </div>
          </div>
          <div className="control-bar" style={controlBarStyle}
               onClick={this.handleControlBarClick}>
            <div className="word-select-container"/>
            <Tooltip placement={isTooltipShowBottom ? 'bottomLeft' : 'topLeft'}
                     overlayClassName={isTooltipShowBottom ? 'tooltip-bottom' : 'tooltip-top'}
                     arrowPointAtCenter
                     title={sizeColorBar}
                     visible={barVisibleType === 'rect'}
                     getPopupContainer={() => document.getElementsByClassName('control-bar')[0]}>
              <span className="rect" onClick={() => this.handleCanvasPrint('rect')}/>
            </Tooltip>
            <Tooltip placement={isTooltipShowBottom ? 'bottomLeft' : 'topLeft'}
                     overlayClassName={isTooltipShowBottom ? 'tooltip-bottom' : 'tooltip-top'}
                     arrowPointAtCenter
                     title={sizeColorBar}
                     visible={barVisibleType === 'circle'}
                     getPopupContainer={() => document.getElementsByClassName('control-bar')[0]}>
              <span className="circle" onClick={() => this.handleCanvasPrint('circle')}/>
            </Tooltip>
            <Tooltip placement={isTooltipShowBottom ? 'bottom' : 'top'}
                     overlayClassName={isTooltipShowBottom ? 'tooltip-bottom' : 'tooltip-top'}
                     arrowPointAtCenter
                     title={sizeColorBar}
                     visible={barVisibleType === 'pencil'}
                     getPopupContainer={() => document.getElementsByClassName('control-bar')[0]}>
              <Icon type="edit" style={{color:'#ccc'}} onClick={() => this.handleCanvasPrint('pencil')}/>
            </Tooltip>
            <Tooltip placement={isTooltipShowBottom ? 'bottom' : 'top'}
                     overlayClassName={isTooltipShowBottom ? 'tooltip-bottom' : 'tooltip-top'}
                     arrowPointAtCenter
                     title={sizeColorBar}
                     visible={barVisibleType === 'word'}
                     getPopupContainer={() => document.getElementsByClassName('control-bar')[0]}>
              <span className="word" onClick={() => this.handleCanvasPrint('word')}>T</span>
            </Tooltip>
            <span className="ant-divider" />
            <Icon type="rollback" className={saveImageData.length > 1 ? 'active' : ''} onClick={this.rollBackEditCanvas}/>
            <Icon type="close" onClick={this.editCancel}/>
            <Icon type="check" onClick={this.editOk}/>
          </div>
        </div>
      </div>
    )
  }
}

function mapStateToProps(state) {
  return { }
}

CanvasEdit.propTypes = {
  imgUrl: React.PropTypes.string,
  onOK: React.PropTypes.func,
  onCancel: React.PropTypes.func,
};

CanvasEdit.defaultProps={
  onOK: () => {},
  onCancel: () => {}
};

const wrappedCanvasEdit = Form.create()(CanvasEdit);

export default connect(mapStateToProps)(wrappedCanvasEdit)
